package com.sojson.config.interceptor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.sojson.base.BaseInterceptor;
import com.sojson.config.response.ResponseBodyEncryptionInterceptor;
import com.sojson.config.response.ResponseBodyJsonInterceptor;
import com.sojson.constant.Constant;
import com.sojson.util.INI4jUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.filter.FilterUtil;
import com.sojson.util.servlet.ServletUtil;
import com.sojson.util.text.Convert;

import lombok.extern.slf4j.Slf4j;

/**
 * 配置拦截器bean
 * 
 * @author liu
 * @date 2020-11-02
 */
@Slf4j
// @Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {

    /** 拦截器权限列表在ini文件中的分组 */
    private String permissionIniInterceptor =
        Convert.toStr(Constant.PROPERTIES.getProperty("so.permission.ini.interceptor"), "interceptor");
    /** 拦截器不过滤权限列表在ini文件中的分组 */
    private String permissionIniInterceptorExclude =
        Convert.toStr(Constant.PROPERTIES.getProperty("so.permission.ini.interceptorExclude"), "interceptor_exclude");

    /**
     * spring boot 的 path 匹配规则
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 常用的两种
        // 匹配结尾 / :会识别 url 的最后一个字符是否为 /
        // localhost:8080/test 与 localhost:8080/test/ 等价
        // configurer.setUseTrailingSlashMatch(true);

        // 给所有控制器的路径添加前缀(为了区分静态资源)
        configurer.addPathPrefix(ServletUtil.METHOD_PATH, (aClass) -> true);
    }

    /**
     * 静态资源路径映射(可以映射本地资源,计算机的文件)
     * 
     * 重写 WebMvcConfigurationSupport之后，会出现静态资源无法访问 所以需要重写 addResourceHandlers
     * 系统默认是static
     * 
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // TODO
        // addResourceHandler 指的是对外暴露的访问路径
        // addResourceLocations 指的是内部文件放置的目录
    }

    /**
     * 控制器转发
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

    }

    /**
     * 添加多个拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用户排除拦截

        // 注册TestInterceptor拦截器
        // InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
        // registration.addPathPatterns("/**"); // 所有路径都被拦截
        // registration.excludePathPatterns( // 添加不拦截路径
        // // "你的登陆路径", //登录
        // "*.html", // html静态资源
        // "*.js", // js静态资源
        // "*.css", // css静态资源
        // "*.woff", "*.ttf");

        // addPathPatterns(registry, new HeadInterceptor());
        addPathPatterns(registry, new ResponseBodyJsonInterceptor());
        addPathPatterns(registry, new ResponseBodyEncryptionInterceptor());
        addPathPatterns(registry, new LoginInterceptor());
        addPathPatterns(registry, new RoleInterceptor());
        addPathPatterns(registry, new PermissionInterceptor());
    }

    /**
     * 
     * @param type 哪种过滤器
     * @return
     */
    @SuppressWarnings("unused")
    private ArrayList<String> getPathPatterns(int type) {
        return FilterUtil.getPathPatterns(type);
    }

    /**
     * 获取权限列表文件的内容
     * 
     * @return
     * @throws IOException
     */
    private INI4jUtil getIni4jUtil() throws IOException {
        return FilterUtil.getIni4jUtil();
    }

    /**
     * 判断一个字符串是否不是空(空对象和空字符串)
     * 
     * @param str
     * @return
     */
    private boolean isNotBlank(Object str) {
        return StringUtil.isNotBlank(str);
    }

    /**
     * 判断一个对象是否是空(空对象)
     * 
     * @param obj
     * @return
     */
    private boolean isBlankObject(Object obj) {
        return StringUtil.isBlankObject(obj);
    }

    /**
     * 判断一个对象是否不是空(空对象)
     * 
     * @param obj
     * @return
     */
    private boolean isNotBlankObject(Object obj) {
        return StringUtil.isNotBlankObject(obj);
    }

    /**
     * 给过滤器添加拦截路径
     * 
     * @param reg
     * @param interceptor
     * @throws IOException 
     */
    private void addPathPatterns(InterceptorRegistry reg, BaseInterceptor interceptor) {
        INI4jUtil ini = null;
        try {
            ini = getIni4jUtil();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        // 添加一个拦截器
        InterceptorRegistration registry = null;
        // 获取当前拦截器的名字
        String name = interceptor.getName();

        // 添加过滤权限
        String section = this.permissionIniInterceptor;
        Set<Entry<String, String>> entrySet = ini.get(section).entrySet();
        for (Entry<String, String> entry : entrySet) {
            String value = entry.getValue();
            if (isNotBlank(value) && value.contains(name)) {
                if (isBlankObject(registry)) {
                    registry = reg.addInterceptor(interceptor);
                }
                registry.addPathPatterns(entry.getKey());
            }
        }

        if (isNotBlankObject(registry)) {
            // 添加不过滤权限
            section = this.permissionIniInterceptorExclude;
            entrySet = ini.get(section).entrySet();
            for (Entry<String, String> entry : entrySet) {
                String value = entry.getValue();
                if (isNotBlank(value) && value.contains(name)) {
                    registry.addPathPatterns(entry.getKey());
                }
            }
        }
    }

}